package de.farbstreich.tozen2.client;




import java.awt.AWTException;
import java.awt.Color;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import de.farbstreich.tozen2.client.board.TozenBoard;
import de.farbstreich.tozen2.client.board.TozenBoard.Move;
import de.farbstreich.tozen2.common.Tools;

/**
 * creates gui frame and set current panel panels: loginPanel, overviewPanel,
 * gamePanel
 * 
 * @author mo
 * 
 */
public class ClientGUIFrame2 extends JFrame {

	private static final long serialVersionUID = 1L;

	public JPanel currentPanel = null;
	public ClientGUIInput guiInput;

	public ClientGUIChat chat = null;
	public ClientGUIGamesOverview gamesOverview = null;
	public TozenBoard gameBoard = null;
	public ClientGUIGameActions gameAction = null;
	public ClientGUILoginPanel login = null;

	public JPanel background = null;
	public JPanel overview = null;
	public JPanel game = null;
	public JPanel loginPanel = null;

	private Dimension windowSize = new Dimension(1000, 700);

	public JLabel[] playerNameLabels = null;

	private JLabel closeButton;

	// Joke
	public boolean MMH = false;

	/**
	 * This is the default constructor
	 * 
	 * @param input
	 * @param gameData
	 */
	public ClientGUIFrame2(ClientGUIInput input) {
		super();
		this.guiInput = input;
		initialize();
	}

	/**
	 * This method initializes frame
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(windowSize);
		this.setMinimumSize(windowSize);
		this.setUndecorated(true);
		this.setTitle("Tozen^2 - Das Spiel");
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				closeGUIFrame();
			}
		});
		this.setContentPane(getCurrentPanel());

	}

	/**
	 * change current panel and display it
	 * 
	 * @param panel
	 */
	public void changePanel(final JPanel panel) {
		try {
			SwingUtilities.invokeLater(new Runnable() {

				public void run() {
					setContentPane(panel);
					currentPanel = panel;
					pack(); // in theory, this is only needed once on setting
					// the new Panel
					invalidate();
					repaint();
				}

			});
		} catch (Exception e) {
			System.out.println("Error: ClientGUIOutput().changePanel := " + e);
		}
	}

	/**
	 * class for create background panel
	 * 
	 * @author mo
	 * 
	 */
	class BackgroundPanel extends JPanel {
		private static final long serialVersionUID = 4541956384696830191L;

		Image image = null;
		BufferedImage bgimage = null;
		final Container window;

		public BackgroundPanel(Container window2) {
			this.window = window2;
			try {
				image = Tools.loadImage("pergament.png");
			} catch (IOException e) {
				e.printStackTrace();
			}
			((ClientGUIFrame2) window2).centerOnScreen(window2);
			loadBG();

		}

		/**
		 * creates image of screen and set it at background of gui
		 */
		public void loadBG() {
			Rectangle rect = window.getBounds();
			try {
				bgimage = new Robot().createScreenCapture(rect);
			} catch (AWTException e) {
				throw new RuntimeException(e.getMessage());
			}
		}

		protected void paintComponent(Graphics g) {
			super.paintComponent(g);

			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			if (bgimage != null)
				g.drawImage(bgimage, 0, 0, this);
			if (image != null)
				g.drawImage(image, 0, 0, this);

		}
	}

	/**
	 * creates and return login panel
	 * 
	 * @return
	 */
	public JPanel getLoginPanel() {
		/*if (this.loginPanel == null) {*/
			loginPanel = new JPanel(null);

			login = new ClientGUILoginPanel(guiInput);
			login.setOpaque(false);
			login.setBounds(new Rectangle(660, 180, 230, 400));

			JLabel imageLabel = new JLabel(new ImageIcon(Tools.getImageURL("knight_big.png")));
			imageLabel.setBounds(new Rectangle(200, 150, 410, 417));
			loginPanel.add(imageLabel, null);

			loginPanel.add(login, null);
			loginPanel.add(getCloseLabel(), null);
			loginPanel.add(getBackgroundPanel(), null);
		/*}*/
		return this.loginPanel;
	}

	/**
	 * show all for overview needen panels
	 * 
	 * @return
	 */
	public JPanel getOverviewPanel() {
		// if (this.overview == null) {
		overview = new JPanel(null);
		overview.setSize(windowSize);
		overview.add(getGamesOverviewPanel());
		overview.add(getChatPanel());
		overview.add(getCloseLabel(), null);
		overview.add(getBackgroundPanel(), null);
		// }
		return this.overview;
	}

	/**
	 * show all for game needen panels
	 * 
	 * @return
	 */
	public JPanel getGamePanel() {
		// if (this.game == null) {
		game = new JPanel(null);
		game.setSize(windowSize);
		game.add(getBoardPanel(), null);
		game.add(getGameActionPanel(), null);
		game.add(getChatPanel(), null);

		JLabel[] playerNames = getPlayerNameLabels();
		for (JLabel playerName : playerNames) {
			game.add(playerName, null);
		}
		game.add(getCloseLabel(), null);
		game.add(getBackgroundPanel(), null);
		// }
		return this.game;
	}

	/**
	 * reset labels for player names
	 */
	public void resetPlayerNameLabels() {
		this.playerNameLabels = new JLabel[4];
		playerNameLabels[0] = new JLabel();
		playerNameLabels[0].setBounds(new Rectangle(120, 50, 230, 64));
		playerNameLabels[0].setIcon(new ImageIcon(Tools
				.getImageURL("u0_King.png")));
		playerNameLabels[0].setEnabled(false);

		playerNameLabels[1] = new JLabel();
		playerNameLabels[1].setBounds(new Rectangle(359, 595, 230, 64));
		playerNameLabels[1].setIcon(new ImageIcon(Tools
				.getImageURL("u1_King.png")));
		playerNameLabels[1].setHorizontalTextPosition(JLabel.LEFT);
		playerNameLabels[1].setHorizontalAlignment(JLabel.RIGHT);
		playerNameLabels[1].setEnabled(false);

		playerNameLabels[2] = new JLabel();
		playerNameLabels[2].setBounds(new Rectangle(359, 50, 230, 64));
		playerNameLabels[2].setIcon(new ImageIcon(Tools
				.getImageURL("u2_King.png")));
		playerNameLabels[2].setHorizontalTextPosition(JLabel.LEFT);
		playerNameLabels[2].setHorizontalAlignment(JLabel.RIGHT);
		playerNameLabels[2].setEnabled(false);

		playerNameLabels[3] = new JLabel();
		playerNameLabels[3].setBounds(new Rectangle(120, 595, 230, 64));
		playerNameLabels[3].setIcon(new ImageIcon(Tools
				.getImageURL("u3_King.png")));
		playerNameLabels[3].setEnabled(false);
	}

	/**
	 * returns playerNameLabels
	 * 
	 * @return
	 */
	public JLabel[] getPlayerNameLabels() {
		if (this.playerNameLabels == null) {
			resetPlayerNameLabels();
		}
		return this.playerNameLabels;
	}

	/**
	 * This method initializes current Panel if currentPanel not set initializes
	 * Login Panel as Current Panel, used by Starting
	 * 
	 * @return javax.swing.JPanel
	 */

	private JPanel getCurrentPanel() {
		if (currentPanel == null) {
			currentPanel = getLoginPanel();
		}
		return currentPanel;
	}

	/**
	 * prints background
	 * 
	 * @return
	 */
	private JPanel getBackgroundPanel() {
		if (background == null) {
			background = new BackgroundPanel(this);
			background.setBounds(new Rectangle(0, 0, 1000, 700));
		}
		return background;
	}

	/**
	 * shows panel with set new game, join game and players list
	 * 
	 * @return
	 */
	public JPanel getGamesOverviewPanel() {
		if (gamesOverview == null) {
			gamesOverview = new ClientGUIGamesOverview();
			gamesOverview.setOpaque(false);
			gamesOverview.setBounds(new Rectangle(120, 120, 469, 469));
			gamesOverview.setInput(guiInput);
		}
		return gamesOverview;
	}

	/**
	 * This method initializes jPanel
	 * 
	 * @return javax.swing.JPanel
	 */
	public JPanel getChatPanel() {
		if (chat == null) {
			chat = new ClientGUIChat();
			chat.setOpaque(false);
			chat.setBounds(new Rectangle(660, 180, 230, 400));
			chat.setInput(guiInput);
		}
		return chat;
	}

	/**
	 * shows gameboard
	 * 
	 * @return JPanel
	 */
	public JPanel getBoardPanel() {
		if (gameBoard == null) {
			gameBoard = new TozenBoard();
			gameBoard.setOpaque(false);
			gameBoard.setBounds(new Rectangle(120, 120, 469, 469));
			gameBoard.addActionListener(new ActionListener() {

				public void actionPerformed(ActionEvent e) {
					Move m = ((TozenBoard) e.getSource()).getLastTry();
					if (m.origin.x == m.target.x && m.origin.y == m.target.y) {
						return;
					}
					guiInput.sendTestMove(m.origin.x, m.origin.y, m.target.x,
							m.target.y);
					((TozenBoard) e.getSource()).setMoveable(false);
				}
			});
		}

		return gameBoard;
	}

	/**
	 * shows GameActionPanel with startButton and surrenderButton
	 * 
	 * @return JPanel
	 */
	public JPanel getGameActionPanel() {
		if (gameAction == null) {
			gameAction = new ClientGUIGameActions();
			gameAction.setOpaque(false);
			gameAction.setBounds(new Rectangle(660, 120, 230, 50));
			gameAction.setInput(guiInput);
			gameAction.getStartButton().setEnabled(false);
		}

		return gameAction;
	}

	public void centerOnScreen(Container c) {
		Dimension paneSize = c.getSize();
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		c.setLocation((screenSize.width - paneSize.width) / 2,
				(screenSize.height - paneSize.height) / 2);
	}

	/**
	 * create and return close Label to close full programm
	 * 
	 * @return
	 */
	public JLabel getCloseLabel() {
		if (this.closeButton == null) {
			closeButton = new JLabel();
			closeButton.setText("Beenden");
			closeButton.setBounds(new Rectangle(900, 40, 100, 25));
			closeButton.setForeground(Color.WHITE);
			closeButton.setFont(new Font("SansSerif", Font.BOLD, 12));
			closeButton.setCursor(new Cursor(Cursor.HAND_CURSOR));

			final ClientGUIFrame2 parent = this;
			closeButton.addMouseListener(new MouseAdapter() {
				public void mouseClicked(MouseEvent e) {
					parent.closeGUIFrame();
				}
			});
		}
		return this.closeButton;
	}

	/**
	 * close Frame and exit
	 */
	private void closeGUIFrame() {
		if (guiInput.getOutputStream() != null) {
			guiInput.sendLogout();
		}
		this.setVisible(false);
		this.dispose();
		System.exit(0);
	}

}
